Added Linux-PAM and updated description.
authorNikos Mavrogiannopoulos <[email protected]>
Wed, 18 Jun 2014 21:52:34 +0000 (23:52 +0200)
committerNikos Mavrogiannopoulos <[email protected]>
Wed, 18 Jun 2014 21:55:33 +0000 (23:55 +0200)
Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
16 files changed:
libs/libpam/Makefile [new file with mode: 0644]
libs/libpam/files/pam.conf [new file with mode: 0644]
libs/libpam/files/pam.d/common-account [new file with mode: 0644]
libs/libpam/files/pam.d/common-auth [new file with mode: 0644]
libs/libpam/files/pam.d/common-password [new file with mode: 0644]
libs/libpam/files/pam.d/common-session [new file with mode: 0644]
libs/libpam/files/pam.d/common-session-noninteractive [new file with mode: 0644]
libs/libpam/files/pam.d/other [new file with mode: 0644]
libs/libpam/patches/000-OE-libpam-xtests.patch [new file with mode: 0644]
libs/libpam/patches/000-OE-pam-no-innetgr.patch [new file with mode: 0644]
libs/libpam/patches/001-no_nis.patch [new file with mode: 0644]
libs/libpam/patches/002-no_yywrap.patch [new file with mode: 0644]
libs/libpam/patches/003-no_doc.patch [new file with mode: 0644]
libs/libpam/patches/004-fix_lib64.patch [new file with mode: 0644]
libs/libpam/patches/005-fix_ruserok.patch [new file with mode: 0644]
libs/libpam/patches/006-fix_xdr.patch [new file with mode: 0644]

diff --git a/libs/libpam/Makefile b/libs/libpam/Makefile
new file mode 100644 (file)
index 0000000..7881c3e
--- /dev/null
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libpam
+PKG_VERSION:=1.1.8
+PKG_RELEASE:=3
+
+PKG_SOURCE:=Linux-PAM-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.linux-pam.org/library/
+PKG_MD5SUM:=35b6091af95981b1b2cd60d813b5e4ee
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+PKG_MAINTAINER:=Nikos Mavrogiannopoulos <[email protected]>
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/Linux-PAM-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libpam
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=the Linux-PAM libraries and modules.
+  URL:=http://www.kernel.org/pub/linux/libs/pam
+endef
+
+define Package/libpam/description
+       The Linux-PAM Pluggable Authentication Modules.
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/Configure
+       $(call Build/Configure/Default, \
+               --enable-shared \
+               --enable-static \
+               --enable-pamlocking \
+               --disable-prelude \
+               --disable-lckpwdf \
+               --disable-selinux \
+               --disable-nls \
+               --disable-rpath \
+               --enable-db=no \
+       )
+endef
+
+define Build/InstallDev
+       $(INSTALL_DIR) $(1)/lib
+       $(INSTALL_DIR) $(1)/usr/include
+       $(CP) $(PKG_INSTALL_DIR)/lib/* $(1)/lib/
+       $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include
+endef
+
+define Package/libpam/install
+       $(INSTALL_DIR) $(1)/lib $(1)/lib/security $(1)/lib/security/pam_filter
+       $(INSTALL_DIR) $(1)/etc $(1)/etc/pam.d
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(CP) $(PKG_INSTALL_DIR)/lib/*.so* $(1)/lib/
+       $(CP) $(PKG_INSTALL_DIR)/lib/security/*.so* $(1)/lib/security/
+       $(CP) $(PKG_INSTALL_DIR)/lib/security/pam_filter/* $(1)/lib/security/pam_filter/
+       $(CP) $(PKG_INSTALL_DIR)/etc/* $(1)/etc/
+       $(CP) ./files/* $(1)/etc/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/* $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,libpam))
diff --git a/libs/libpam/files/pam.conf b/libs/libpam/files/pam.conf
new file mode 100644 (file)
index 0000000..3eeb72d
--- /dev/null
@@ -0,0 +1,15 @@
+# ---------------------------------------------------------------------------#
+# /etc/pam.conf                                                                     #
+# ---------------------------------------------------------------------------#
+#
+# NOTE
+# ----
+#
+# NOTE: Most program use a file under the /etc/pam.d/ directory to setup their
+# PAM service modules. This file is used only if that directory does not exist.
+# ---------------------------------------------------------------------------#
+
+# Format:
+# serv.        module     ctrl       module [path]     ...[args..]                  #
+# name type       flag                                                      #
+
diff --git a/libs/libpam/files/pam.d/common-account b/libs/libpam/files/pam.d/common-account
new file mode 100644 (file)
index 0000000..7162548
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# /etc/pam.d/common-account - authorization settings common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of the authorization modules that define
+# the central access policy for use on the system.  The default is to
+# only deny service to users whose accounts are expired in /etc/shadow.
+#
+
+# here are the per-package modules (the "Primary" block)
+account        [success=1 new_authtok_reqd=done default=ignore]        pam_unix.so 
+# here's the fallback if no module succeeds
+account        requisite                       pam_deny.so
+# prime the stack with a positive return value if there isn't one already;
+# this avoids us returning an error just because nothing sets a success code
+# since the modules above will each just jump around
+account        required                        pam_permit.so
+# and here are more per-package modules (the "Additional" block)
+
+# end of pam-auth-update config
diff --git a/libs/libpam/files/pam.d/common-auth b/libs/libpam/files/pam.d/common-auth
new file mode 100644 (file)
index 0000000..8fc529d
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# /etc/pam.d/common-auth - authentication settings common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of the authentication modules that define
+# the central authentication scheme for use on the system
+# (e.g., /etc/shadow, LDAP, Kerberos, etc.).  The default is to use the
+# traditional Unix authentication mechanisms.
+#
+
+# here are the per-package modules (the "Primary" block)
+auth   [success=1 default=ignore]      pam_unix.so nullok_secure
+# here's the fallback if no module succeeds
+auth   requisite                       pam_deny.so
+# prime the stack with a positive return value if there isn't one already;
+# this avoids us returning an error just because nothing sets a success code
+# since the modules above will each just jump around
+auth   required                        pam_permit.so
+# and here are more per-package modules (the "Additional" block)
+
+# end of pam-auth-update config
diff --git a/libs/libpam/files/pam.d/common-password b/libs/libpam/files/pam.d/common-password
new file mode 100644 (file)
index 0000000..5d0dee0
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# /etc/pam.d/common-password - password-related modules common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of modules that define the services to be
+# used to change user passwords.  The default is pam_unix.
+
+# Explanation of pam_unix options:
+#
+# The "sha512" option enables salted SHA512 passwords.  Without this option,
+# the default is Unix crypt.  Prior releases used the option "md5".
+#
+# The "obscure" option replaces the old `OBSCURE_CHECKS_ENAB' option in
+# login.defs.
+#
+# See the pam_unix manpage for other options.
+
+# here are the per-package modules (the "Primary" block)
+password       [success=1 default=ignore]      pam_unix.so obscure sha512
+# here's the fallback if no module succeeds
+password       requisite                       pam_deny.so
+# prime the stack with a positive return value if there isn't one already;
+# this avoids us returning an error just because nothing sets a success code
+# since the modules above will each just jump around
+password       required                        pam_permit.so
+# and here are more per-package modules (the "Additional" block)
+
+# end of pam-auth-update config
diff --git a/libs/libpam/files/pam.d/common-session b/libs/libpam/files/pam.d/common-session
new file mode 100644 (file)
index 0000000..f0d41cc
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# /etc/pam.d/common-session - session-related modules common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of modules that define tasks to be performed
+# at the start and end of sessions of *any* kind (both interactive and
+# non-interactive).
+#
+
+# here are the per-package modules (the "Primary" block)
+session        [default=1]                     pam_permit.so
+# here's the fallback if no module succeeds
+session        requisite                       pam_deny.so
+# prime the stack with a positive return value if there isn't one already;
+# this avoids us returning an error just because nothing sets a success code
+# since the modules above will each just jump around
+session        required                        pam_permit.so
+# The pam_umask module will set the umask according to the system default in
+# /etc/login.defs and user settings, solving the problem of different
+# umask settings with different shells, display managers, remote sessions etc.
+# See "man pam_umask".
+session optional                       pam_umask.so
+# and here are more per-package modules (the "Additional" block)
+session        required                        pam_unix.so 
+# end of pam-auth-update config
diff --git a/libs/libpam/files/pam.d/common-session-noninteractive b/libs/libpam/files/pam.d/common-session-noninteractive
new file mode 100644 (file)
index 0000000..f4943e1
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# /etc/pam.d/common-session-noninteractive - session-related modules
+# common to all non-interactive services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of modules that define tasks to be performed
+# at the start and end of all non-interactive sessions.
+#
+
+# here are the per-package modules (the "Primary" block)
+session        [default=1]                     pam_permit.so
+# here's the fallback if no module succeeds
+session        requisite                       pam_deny.so
+# prime the stack with a positive return value if there isn't one already;
+# this avoids us returning an error just because nothing sets a success code
+# since the modules above will each just jump around
+session        required                        pam_permit.so
+# The pam_umask module will set the umask according to the system default in
+# /etc/login.defs and user settings, solving the problem of different
+# umask settings with different shells, display managers, remote sessions etc.
+# See "man pam_umask".
+session optional                       pam_umask.so
+# and here are more per-package modules (the "Additional" block)
+session        required                        pam_unix.so 
+# end of pam-auth-update config
diff --git a/libs/libpam/files/pam.d/other b/libs/libpam/files/pam.d/other
new file mode 100644 (file)
index 0000000..6679e4f
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# /etc/pam.d/other - specify the PAM fallback behaviour
+#
+# Note that this file is used for any unspecified service; for example
+#if /etc/pam.d/cron  specifies no session modules but cron calls
+#pam_open_session, the session module out of /etc/pam.d/other is
+#used.  If you really want nothing to happen then use pam_permit.so or
+#pam_deny.so as appropriate.
+
+# We fall back to the system default in /etc/pam.d/common-*
+# 
+
+auth       include      common-auth
+account    include      common-account
+password   include      common-password
+session    include      common-session
diff --git a/libs/libpam/patches/000-OE-libpam-xtests.patch b/libs/libpam/patches/000-OE-libpam-xtests.patch
new file mode 100644 (file)
index 0000000..19fbaa2
--- /dev/null
@@ -0,0 +1,35 @@
+This patch is used to create a new sub package libpam-xtests to do more checks.
+
+Upstream-Status: Pending
+
+Signed-off-by: Kang Kai <[email protected]>
+--- a/xtests/Makefile.am
++++ b/xtests/Makefile.am
+@@ -7,7 +7,7 @@ AM_CFLAGS = -DLIBPAM_COMPILE -I$(top_src
+ LDADD = $(top_builddir)/libpam/libpam.la \
+       $(top_builddir)/libpam_misc/libpam_misc.la
+-CLEANFILES = *~ $(XTESTS)
++CLEANFILES = *~
+ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \
+       tst-pam_dispatch3.pamd tst-pam_dispatch4.pamd \
+@@ -51,3 +51,18 @@ EXTRA_PROGRAMS = $(XTESTS)
+ xtests: $(XTESTS) run-xtests.sh
+       "$(srcdir)"/run-xtests.sh "$(srcdir)" ${XTESTS} ${NOSRCTESTS}
++
++all: $(XTESTS)
++
++install: install_xtests
++
++install_xtests:
++      $(INSTALL) -d $(DESTDIR)$(pkgdatadir)/xtests
++      for file in $(EXTRA_DIST) ; do \
++              $(INSTALL) $$file $(DESTDIR)$(pkgdatadir)/xtests ; \
++      done
++      for file in $(XTESTS); do \
++              $(INSTALL) .libs/$$file $(DESTDIR)$(pkgdatadir)/xtests ; \
++      done
++
++.PHONY: all install_xtests
diff --git a/libs/libpam/patches/000-OE-pam-no-innetgr.patch b/libs/libpam/patches/000-OE-pam-no-innetgr.patch
new file mode 100644 (file)
index 0000000..f7f5b48
--- /dev/null
@@ -0,0 +1,85 @@
+innetgr may not be there so make sure that when innetgr is not present
+then we inform about it and not use it.
+
+-Khem
+--- a/modules/pam_group/pam_group.c
++++ b/modules/pam_group/pam_group.c
+@@ -656,7 +656,11 @@ static int check_account(pam_handle_t *p
+       }
+       /* If buffer starts with @, we are using netgroups */
+       if (buffer[0] == '@')
++#ifdef HAVE_INNETGR
+         good &= innetgr (&buffer[1], NULL, user, NULL);
++#else
++      pam_syslog (pamh, LOG_ERR, "pam_group does not have netgroup support");
++#endif
+       /* otherwise, if the buffer starts with %, it's a UNIX group */
+       else if (buffer[0] == '%')
+           good &= pam_modutil_user_in_group_nam_nam(pamh, user, &buffer[1]);
+--- a/modules/pam_time/pam_time.c
++++ b/modules/pam_time/pam_time.c
+@@ -555,9 +555,13 @@ check_account(pam_handle_t *pamh, const
+         }
+         /* If buffer starts with @, we are using netgroups */
+         if (buffer[0] == '@')
+-          good &= innetgr (&buffer[1], NULL, user, NULL);
++#ifdef HAVE_INNETGR
++             good &= innetgr (&buffer[1], NULL, user, NULL);
++#else
++             pam_syslog (pamh, LOG_ERR, "pam_time does not have netgroup support");
++#endif
+         else
+-          good &= logic_field(pamh, user, buffer, count, is_same);
++             good &= logic_field(pamh, user, buffer, count, is_same);
+         D(("with user: %s", good ? "passes":"fails" ));
+         /* here we get the time field */
+--- a/modules/pam_succeed_if/pam_succeed_if.c
++++ b/modules/pam_succeed_if/pam_succeed_if.c
+@@ -231,18 +231,27 @@ evaluate_notingroup(pam_handle_t *pamh,
+ }
+ /* Return PAM_SUCCESS if the (host,user) is in the netgroup. */
+ static int
+-evaluate_innetgr(const char *host, const char *user, const char *group)
++evaluate_innetgr(const pam_handle_t* pamh, const char *host, const char *user, const char *group)
+ {
++#ifdef HAVE_INNETGR
+       if (innetgr(group, host, user, NULL) == 1)
+               return PAM_SUCCESS;
++#else
++        pam_syslog (pamh, LOG_ERR, "pam_succeed_if does not have netgroup support");
++#endif
++
+       return PAM_AUTH_ERR;
+ }
+ /* Return PAM_SUCCESS if the (host,user) is NOT in the netgroup. */
+ static int
+-evaluate_notinnetgr(const char *host, const char *user, const char *group)
++evaluate_notinnetgr(const pam_handle_t* pamh, const char *host, const char *user, const char *group)
+ {
++#ifdef HAVE_INNETGR
+       if (innetgr(group, host, user, NULL) == 0)
+               return PAM_SUCCESS;
++#else
++      pam_syslog (pamh, LOG_ERR, "pam_succeed_if does not have netgroup support");
++#endif
+       return PAM_AUTH_ERR;
+ }
+@@ -387,14 +396,14 @@ evaluate(pam_handle_t *pamh, int debug,
+               const void *rhost;
+               if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS)
+                       rhost = NULL;
+-              return evaluate_innetgr(rhost, user, right);
++              return evaluate_innetgr(pamh, rhost, user, right);
+       }
+       /* (Rhost, user) is not in this group. */
+       if (strcasecmp(qual, "notinnetgr") == 0) {
+               const void *rhost;
+               if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS)
+                       rhost = NULL;
+-              return evaluate_notinnetgr(rhost, user, right);
++              return evaluate_notinnetgr(pamh, rhost, user, right);
+       }
+       /* Fail closed. */
+       return PAM_SERVICE_ERR;
diff --git a/libs/libpam/patches/001-no_nis.patch b/libs/libpam/patches/001-no_nis.patch
new file mode 100644 (file)
index 0000000..c9988c7
--- /dev/null
@@ -0,0 +1,68 @@
+--- a/modules/pam_access/pam_access.c
++++ b/modules/pam_access/pam_access.c
+@@ -44,7 +44,7 @@
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <sys/socket.h>
+-#ifdef HAVE_RPCSVC_YPCLNT_H
++#ifdef HAVE_RPCSVC_YPCLNT_H && USE_NIS
+ #include <rpcsvc/ypclnt.h>
+ #endif
+ #ifdef HAVE_LIBAUDIT
+--- a/modules/pam_unix/pam_unix_passwd.c
++++ b/modules/pam_unix/pam_unix_passwd.c
+@@ -79,18 +79,18 @@
+ #include "passverify.h"
+ #include "bigcrypt.h"
+-#if (HAVE_YP_GET_DEFAULT_DOMAIN || HAVE_GETDOMAINNAME) && HAVE_YP_MASTER
++#if (HAVE_YP_GET_DEFAULT_DOMAIN || HAVE_GETDOMAINNAME) && HAVE_YP_MASTER && USE_NIS
+ # define HAVE_NIS
+ #endif
+ #ifdef HAVE_NIS
+ # include <rpc/rpc.h>
+-# if HAVE_RPCSVC_YP_PROT_H
++# if HAVE_RPCSVC_YP_PROT_H && USE_NIS
+ #  include <rpcsvc/yp_prot.h>
+ # endif
+-# if HAVE_RPCSVC_YPCLNT_H
++# if HAVE_RPCSVC_YPCLNT_H && USE_NIS
+ #  include <rpcsvc/ypclnt.h>
+ # endif
+--- a/modules/pam_unix/support.c
++++ b/modules/pam_unix/support.c
+@@ -19,7 +19,7 @@
+ #include <ctype.h>
+ #include <syslog.h>
+ #include <sys/resource.h>
+-#ifdef HAVE_RPCSVC_YPCLNT_H
++#ifdef HAVE_RPCSVC_YPCLNT_H && USE_NIS
+ #include <rpcsvc/ypclnt.h>
+ #endif
+@@ -402,7 +402,7 @@ int _unix_getpwnam(pam_handle_t *pamh, c
+               }
+       }
+-#if defined(HAVE_YP_GET_DEFAULT_DOMAIN) && defined (HAVE_YP_BIND) && defined (HAVE_YP_MATCH) && defined (HAVE_YP_UNBIND)
++#if defined(HAVE_YP_GET_DEFAULT_DOMAIN) && defined (HAVE_YP_BIND) && defined (HAVE_YP_MATCH) && defined (HAVE_YP_UNBIND) && (USE_NIS)
+       if (!matched && nis) {
+               char *userinfo = NULL, *domain = NULL;
+               int len = 0, i;
+--- a/modules/pam_unix/yppasswd_xdr.c
++++ b/modules/pam_unix/yppasswd_xdr.c
+@@ -15,6 +15,10 @@
+ #ifdef HAVE_RPC_RPC_H
+ #include <rpc/rpc.h>
++#ifdef USE_NIS
++#include <rpcsvc/yp_prot.h>
++#include <rpcsvc/ypclnt.h>
++#endif
+ #include "yppasswd.h"
+ bool_t
diff --git a/libs/libpam/patches/002-no_yywrap.patch b/libs/libpam/patches/002-no_yywrap.patch
new file mode 100644 (file)
index 0000000..0d73e4b
--- /dev/null
@@ -0,0 +1,26 @@
+--- a/conf/pam_conv1/pam_conv_l.c
++++ b/conf/pam_conv1/pam_conv_l.c
+@@ -534,7 +534,9 @@ void yyset_lineno (int line_number  );
+ #ifdef __cplusplus
+ extern "C" int yywrap (void );
+ #else
+-extern int yywrap (void );
++int yywrap (void ) {
++      return 1;
++}
+ #endif
+ #endif
+--- a/doc/specs/parse_l.c
++++ b/doc/specs/parse_l.c
+@@ -520,7 +520,9 @@ void yyset_lineno (int line_number  );
+ #ifdef __cplusplus
+ extern "C" int yywrap (void );
+ #else
+-extern int yywrap (void );
++int yywrap (void ) {
++      return 1;
++}
+ #endif
+ #endif
diff --git a/libs/libpam/patches/003-no_doc.patch b/libs/libpam/patches/003-no_doc.patch
new file mode 100644 (file)
index 0000000..d366215
--- /dev/null
@@ -0,0 +1,22 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -4,7 +4,7 @@
+ AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 check-news
+-SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests
++SUBDIRS = libpam tests libpamc libpam_misc modules po conf examples xtests
+ CLEANFILES = *~
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -288,7 +288,7 @@ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+ AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 check-news
+-SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests
++SUBDIRS = libpam tests libpamc libpam_misc modules po conf examples xtests
+ CLEANFILES = *~
+ EXTRA_DIST = pgp.keys.asc CHANGELOG ChangeLog-CVS Copyright Make.xml.rules
+ ACLOCAL_AMFLAGS = -I m4
diff --git a/libs/libpam/patches/004-fix_lib64.patch b/libs/libpam/patches/004-fix_lib64.patch
new file mode 100644 (file)
index 0000000..5605d82
--- /dev/null
@@ -0,0 +1,16 @@
+--- a/configure.in
++++ b/configure.in
+@@ -28,12 +28,7 @@ dnl If we use /usr as prefix, use /etc f
+         fi
+       if test ${libdir} = '${exec_prefix}/lib'
+       then
+-              case "`uname -m`" in
+-                  x86_64|ppc64|s390x|sparc64)
+-                      libdir="/lib64" ;;
+-                  *)
+-                      libdir="/lib" ;;
+-              esac
++              libdir="/lib"
+       fi
+       if test ${sbindir} = '${exec_prefix}/sbin'
+         then
diff --git a/libs/libpam/patches/005-fix_ruserok.patch b/libs/libpam/patches/005-fix_ruserok.patch
new file mode 100644 (file)
index 0000000..1f0f463
--- /dev/null
@@ -0,0 +1,364 @@
+--- a/modules/pam_rhosts/pam_rhosts.c
++++ b/modules/pam_rhosts/pam_rhosts.c
+@@ -43,6 +43,361 @@
+ #include <security/pam_modutil.h>
+ #include <security/pam_ext.h>
++#ifdef __UCLIBC__
++
++#include <stdio.h>
++#include <sys/stat.h>
++
++
++int  __check_rhosts_file = 1;
++
++/* Extremely paranoid file open function. */
++static FILE *
++iruserfopen (const char *file, uid_t okuser)
++{
++  struct stat st;
++  char *cp = NULL;
++  FILE *res = NULL;
++
++  /* If not a regular file, if owned by someone other than user or
++     root, if writeable by anyone but the owner, or if hardlinked
++     anywhere, quit.  */
++  if (lstat (file, &st))
++    cp = "lstat failed";
++  else if (!S_ISREG (st.st_mode))
++    cp = "not regular file";
++  else
++    {
++      res = fopen (file, "r");
++      if (!res)
++      cp = "cannot open";
++      else if (fstat (fileno (res), &st) < 0)
++      cp = "fstat failed";
++      else if (st.st_uid && st.st_uid != okuser)
++      cp = "bad owner";
++      else if (st.st_mode & (S_IWGRP|S_IWOTH))
++      cp = "writeable by other than owner";
++      else if (st.st_nlink > 1)
++      cp = "hard linked somewhere";
++    }
++
++  /* If there were any problems, quit.  */
++  if (cp != NULL)
++    {
++      if (res)
++      fclose (res);
++      return NULL;
++    }
++
++  return res;
++}
++
++/*
++ * Returns 1 for blank lines (or only comment lines) and 0 otherwise
++ */
++static int
++__isempty(char *p)
++{
++    while (*p && isspace (*p)) {
++      ++p;
++    }
++
++    return (*p == '\0' || *p == '#') ? 1 : 0 ;
++}
++
++/* Returns 1 on positive match, 0 on no match, -1 on negative match.  */
++static int
++__icheckhost (u_int32_t raddr, char *lhost, const char *rhost)
++{
++      struct hostent *hp;
++      u_int32_t laddr;
++      int negate=1;    /* Multiply return with this to get -1 instead of 1 */
++      char **pp;
++
++#ifdef __UCLIBC_HAS_REENTRANT_RPC__
++      int save_errno;
++      size_t buflen;
++      char *buffer;
++      struct hostent hostbuf;
++      int herr;
++#endif
++
++#ifdef HAVE_NETGROUP
++      /* Check nis netgroup.  */
++      if (strncmp ("+@", lhost, 2) == 0)
++              return innetgr (&lhost[2], rhost, NULL, NULL);
++
++      if (strncmp ("-@", lhost, 2) == 0)
++              return -innetgr (&lhost[2], rhost, NULL, NULL);
++#endif /* HAVE_NETGROUP */
++
++      /* -host */
++      if (strncmp ("-", lhost,1) == 0) {
++              negate = -1;
++              lhost++;
++      } else if (strcmp ("+",lhost) == 0) {
++              return 1;                    /* asking for trouble, but ok.. */
++      }
++
++      /* Try for raw ip address first. */
++      if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE)
++              return negate * (! (raddr ^ laddr));
++
++      /* Better be a hostname. */
++#ifdef __UCLIBC_HAS_REENTRANT_RPC__
++      buflen = 1024;
++      buffer = malloc(buflen);
++      save_errno = errno;
++
++      while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr)
++             != 0) {
++          free(buffer);
++          return (0);
++      }
++      free(buffer);
++      __set_errno (save_errno);
++#else
++      hp = gethostbyname(lhost);
++#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */
++
++      if (hp == NULL)
++              return 0;
++
++      /* Spin through ip addresses. */
++      for (pp = hp->h_addr_list; *pp; ++pp)
++              if (!memcmp (&raddr, *pp, sizeof (u_int32_t)))
++                      return negate;
++
++      /* No match. */
++      return (0);
++}
++
++/* Returns 1 on positive match, 0 on no match, -1 on negative match.  */
++static int
++__icheckuser (const char *luser, const char *ruser)
++{
++
++    /*
++      luser is user entry from .rhosts/hosts.equiv file
++      ruser is user id on remote host
++      */
++
++#ifdef HAVE_NETGROUP
++    /* [-+]@netgroup */
++    if (strncmp ("+@", luser, 2) == 0)
++      return innetgr (&luser[2], NULL, ruser, NULL);
++
++    if (strncmp ("-@", luser,2) == 0)
++      return -innetgr (&luser[2], NULL, ruser, NULL);
++#endif /* HAVE_NETGROUP */
++
++    /* -user */
++    if (strncmp ("-", luser, 1) == 0)
++      return -(strcmp (&luser[1], ruser) == 0);
++
++    /* + */
++    if (strcmp ("+", luser) == 0)
++      return 1;
++
++    /* simple string match */
++    return strcmp (ruser, luser) == 0;
++}
++
++/*
++ * Returns 0 if positive match, -1 if _not_ ok.
++ */
++static int
++__ivaliduser2(FILE *hostf, u_int32_t raddr,   const char *luser,
++                        const char *ruser, const char *rhost)
++{
++    register const char *user;
++    register char *p;
++    int hcheck, ucheck;
++    char *buf = NULL;
++    size_t bufsize = 0;
++    int retval = -1;
++
++    while (getline (&buf, &bufsize, hostf) > 0) {
++      buf[bufsize - 1] = '\0'; /* Make sure it's terminated.  */
++        p = buf;
++
++      /* Skip empty or comment lines */
++      if (__isempty (p)) {
++          continue;
++      }
++
++      /* Skip lines that are too long. */
++      if (strchr (p, '\n') == NULL) {
++          int ch = getc_unlocked (hostf);
++
++          while (ch != '\n' && ch != EOF)
++            ch = getc_unlocked (hostf);
++          continue;
++      }
++
++      for (;*p && !isspace(*p); ++p) {
++          *p = tolower (*p);
++      }
++
++      /* Next we want to find the permitted name for the remote user.  */
++      if (*p == ' ' || *p == '\t') {
++          /* <nul> terminate hostname and skip spaces */
++          for (*p++='\0'; *p && isspace (*p); ++p);
++
++          user = p;                   /* this is the user's name */
++          while (*p && !isspace (*p))
++              ++p;                    /* find end of user's name */
++      } else
++          user = p;
++
++      *p = '\0';              /* <nul> terminate username (+host?) */
++
++      /* buf -> host(?) ; user -> username(?) */
++
++      /* First check host part */
++      hcheck = __icheckhost (raddr, buf, rhost);
++
++      if (hcheck < 0)
++          break;
++
++      if (hcheck) {
++          /* Then check user part */
++          if (! (*user))
++              user = luser;
++
++          ucheck = __icheckuser (user, ruser);
++
++          /* Positive 'host user' match? */
++          if (ucheck > 0) {
++              retval = 0;
++              break;
++          }
++
++          /* Negative 'host -user' match? */
++          if (ucheck < 0)
++              break;
++
++          /* Neither, go on looking for match */
++      }
++    }
++
++    free (buf);
++
++    return retval;
++}
++
++static int
++iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser,
++                 const char *rhost)
++{
++      FILE *hostf = NULL;
++      int isbad = -1;
++
++      if (!superuser)
++              hostf = iruserfopen (_PATH_HEQUIV, 0);
++
++      if (hostf) {
++              isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
++              fclose (hostf);
++
++              if (!isbad)
++                      return 0;
++      }
++
++      if (__check_rhosts_file || superuser) {
++              char *pbuf;
++              struct passwd *pwd;
++              size_t dirlen;
++              uid_t uid;
++
++#ifdef __UCLIBC_HAS_REENTRANT_RPC__
++              size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
++              struct passwd pwdbuf;
++              char *buffer = stack_heap_alloc(buflen);
++
++              if (getpwnam_r (luser, &pwdbuf, buffer,
++                          buflen, &pwd) != 0 || pwd == NULL)
++              {
++                      stack_heap_free(buffer);
++                      return -1;
++              }
++              stack_heap_free(buffer);
++#else
++              if ((pwd = getpwnam(luser)) == NULL)
++                      return -1;
++#endif
++
++              dirlen = strlen (pwd->pw_dir);
++              pbuf = malloc (dirlen + sizeof "/.rhosts");
++              strcpy (pbuf, pwd->pw_dir);
++              strcat (pbuf, "/.rhosts");
++
++              /* Change effective uid while reading .rhosts.  If root and
++                 reading an NFS mounted file system, can't read files that
++                 are protected read/write owner only.  */
++              uid = geteuid ();
++              seteuid (pwd->pw_uid);
++              hostf = iruserfopen (pbuf, pwd->pw_uid);
++              free(pbuf);
++
++              if (hostf != NULL) {
++                      isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
++                      fclose (hostf);
++              }
++
++              seteuid (uid);
++              return isbad;
++      }
++      return -1;
++}
++
++int ruserok(const char *rhost, int superuser, const char *ruser,
++                      const char *luser)
++{
++        struct hostent *hp;
++      u_int32_t addr;
++      char **ap;
++#ifdef __UCLIBC_HAS_REENTRANT_RPC__
++      size_t buflen;
++      char *buffer;
++      int herr;
++      struct hostent hostbuf;
++#endif
++
++#ifdef __UCLIBC_HAS_REENTRANT_RPC__
++      buflen = 1024;
++      buffer = stack_heap_alloc(buflen);
++
++      while (gethostbyname_r (rhost, &hostbuf, buffer,
++                  buflen, &hp, &herr) != 0 || hp == NULL)
++      {
++          if (herr != NETDB_INTERNAL || errno != ERANGE) {
++              stack_heap_free(buffer);
++              return -1;
++          } else
++          {
++              /* Enlarge the buffer.  */
++              buflen *= 2;
++              stack_heap_free(buffer);
++              buffer = stack_heap_alloc(buflen);
++          }
++      }
++      stack_heap_free(buffer);
++#else
++      if ((hp = gethostbyname(rhost)) == NULL) {
++              return -1;
++      }
++#endif
++      for (ap = hp->h_addr_list; *ap; ++ap) {
++              memmove(&addr, *ap, sizeof(addr));
++              if (iruserok2(addr, superuser, ruser, luser, rhost) == 0)
++                      return 0;
++      }
++      return -1;
++}
++
++#endif /* __UCLIBC__ */
++
+ PAM_EXTERN
+ int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc,
+                        const char **argv)
diff --git a/libs/libpam/patches/006-fix_xdr.patch b/libs/libpam/patches/006-fix_xdr.patch
new file mode 100644 (file)
index 0000000..9769506
--- /dev/null
@@ -0,0 +1,271 @@
+--- a/modules/pam_unix/yppasswd_xdr.c
++++ b/modules/pam_unix/yppasswd_xdr.c
+@@ -21,6 +21,268 @@
+ #endif
+ #include "yppasswd.h"
++#ifdef __UCLIBC__
++
++static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
++
++/*
++ * XDR integers
++ */
++bool_t
++xdr_int (XDR *xdrs, int *ip)
++{
++
++#if INT_MAX < LONG_MAX
++  long l;
++
++  switch (xdrs->x_op)
++    {
++    case XDR_ENCODE:
++      l = (long) *ip;
++      return XDR_PUTLONG (xdrs, &l);
++
++    case XDR_DECODE:
++      if (!XDR_GETLONG (xdrs, &l))
++      {
++        return FALSE;
++      }
++      *ip = (int) l;
++    case XDR_FREE:
++      return TRUE;
++    }
++  return FALSE;
++#elif INT_MAX == LONG_MAX
++  return xdr_long (xdrs, (long *) ip);
++#elif INT_MAX == SHRT_MAX
++  return xdr_short (xdrs, (short *) ip);
++#else
++#error unexpected integer sizes in xdr_int()
++#endif
++}
++
++/*
++ * XDR null terminated ASCII strings
++ * xdr_string deals with "C strings" - arrays of bytes that are
++ * terminated by a NULL character.  The parameter cpp references a
++ * pointer to storage; If the pointer is null, then the necessary
++ * storage is allocated.  The last parameter is the max allowed length
++ * of the string as specified by a protocol.
++ */
++bool_t
++xdr_string (XDR *xdrs, char **cpp, u_int maxsize)
++{
++  char *sp = *cpp;    /* sp is the actual string pointer */
++  u_int size;
++  u_int nodesize;
++
++  /*
++   * first deal with the length since xdr strings are counted-strings
++   */
++  switch (xdrs->x_op)
++    {
++    case XDR_FREE:
++      if (sp == NULL)
++      {
++        return TRUE;          /* already free */
++      }
++      /* fall through... */
++    case XDR_ENCODE:
++      if (sp == NULL)
++      return FALSE;
++      size = strlen (sp);
++      break;
++    case XDR_DECODE:
++      break;
++    }
++  if (!xdr_u_int (xdrs, &size))
++    {
++      return FALSE;
++    }
++  if (size > maxsize)
++    {
++      return FALSE;
++    }
++  nodesize = size + 1;
++
++  /*
++   * now deal with the actual bytes
++   */
++  switch (xdrs->x_op)
++    {
++    case XDR_DECODE:
++      if (nodesize == 0)
++      {
++        return TRUE;
++      }
++      if (sp == NULL)
++      *cpp = sp = (char *) mem_alloc (nodesize);
++      if (sp == NULL)
++      {
++#ifdef USE_IN_LIBIO
++        if (_IO_fwide (stderr, 0) > 0)
++          (void) fwprintf (stderr, L"%s",
++                             _("xdr_string: out of memory\n"));
++        else
++#endif
++          (void) fputs (_("xdr_string: out of memory\n"), stderr);
++        return FALSE;
++      }
++      sp[size] = 0;
++      /* fall into ... */
++
++    case XDR_ENCODE:
++      return xdr_opaque (xdrs, sp, size);
++
++    case XDR_FREE:
++      mem_free (sp, nodesize);
++      *cpp = NULL;
++      return TRUE;
++    }
++  return FALSE;
++}
++
++/*
++ * XDR long integers
++ * The definition of xdr_long() is kept for backward
++ * compatibility. Instead xdr_int() should be used.
++ */
++bool_t
++xdr_long (XDR *xdrs, long *lp)
++{
++  if (xdrs->x_op == XDR_ENCODE
++      && (sizeof (int32_t) == sizeof (long)
++        || (int32_t) *lp == *lp))
++    return XDR_PUTLONG (xdrs, lp);
++
++  if (xdrs->x_op == XDR_DECODE)
++    return XDR_GETLONG (xdrs, lp);
++
++  if (xdrs->x_op == XDR_FREE)
++    return TRUE;
++
++  return FALSE;
++}
++
++/*
++ * XDR unsigned integers
++ */
++bool_t
++xdr_u_int (XDR *xdrs, u_int *up)
++{
++#if UINT_MAX < ULONG_MAX
++  u_long l;
++
++  switch (xdrs->x_op)
++    {
++    case XDR_ENCODE:
++      l = (u_long) * up;
++      return XDR_PUTLONG (xdrs, (long *) &l);
++
++    case XDR_DECODE:
++      if (!XDR_GETLONG (xdrs, (long *) &l))
++      {
++        return FALSE;
++      }
++      *up = (u_int) l;
++    case XDR_FREE:
++      return TRUE;
++    }
++  return FALSE;
++#elif UINT_MAX == ULONG_MAX
++  return xdr_u_long (xdrs, (u_long *) up);
++#elif UINT_MAX == USHRT_MAX
++  return xdr_short (xdrs, (short *) up);
++#else
++#error unexpected integer sizes in xdr_u_int()
++#endif
++}
++
++/*
++ * XDR opaque data
++ * Allows the specification of a fixed size sequence of opaque bytes.
++ * cp points to the opaque object and cnt gives the byte length.
++ */
++bool_t
++xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
++{
++  u_int rndup;
++  static char crud[BYTES_PER_XDR_UNIT];
++
++  /*
++   * if no data we are done
++   */
++  if (cnt == 0)
++    return TRUE;
++
++  /*
++   * round byte count to full xdr units
++   */
++  rndup = cnt % BYTES_PER_XDR_UNIT;
++  if (rndup > 0)
++    rndup = BYTES_PER_XDR_UNIT - rndup;
++
++  switch (xdrs->x_op)
++    {
++    case XDR_DECODE:
++      if (!XDR_GETBYTES (xdrs, cp, cnt))
++      {
++        return FALSE;
++      }
++      if (rndup == 0)
++      return TRUE;
++      return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
++
++    case XDR_ENCODE:
++      if (!XDR_PUTBYTES (xdrs, cp, cnt))
++      {
++        return FALSE;
++      }
++      if (rndup == 0)
++      return TRUE;
++      return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
++
++    case XDR_FREE:
++      return TRUE;
++    }
++  return FALSE;
++}
++
++/*
++ * XDR unsigned long integers
++ * The definition of xdr_u_long() is kept for backward
++ * compatibility. Instead xdr_u_int() should be used.
++ */
++bool_t
++xdr_u_long (XDR *xdrs, u_long *ulp)
++{
++  switch (xdrs->x_op)
++    {
++    case XDR_DECODE:
++      {
++      long int tmp;
++
++      if (XDR_GETLONG (xdrs, &tmp) == FALSE)
++        return FALSE;
++
++      *ulp = (uint32_t) tmp;
++      return TRUE;
++      }
++
++    case XDR_ENCODE:
++      if (sizeof (uint32_t) != sizeof (u_long)
++        && (uint32_t) *ulp != *ulp)
++      return FALSE;
++
++      return XDR_PUTLONG (xdrs, (long *) ulp);
++
++    case XDR_FREE:
++      return TRUE;
++    }
++  return FALSE;
++}
++
++#endif /* UCLIBC */
++
+ bool_t
+ xdr_xpasswd(XDR * xdrs, xpasswd * objp)
+ {